#ifndef _XDB_THREAD_H
#define _XDB_THREAD_H

#include <deque>
#include <vector>
#include <stack>

namespace xdragonball
{
class MutexLock
{
public:
	MutexLock(const pthread_mutexattr_t *attr=NULL) { pthread_mutex_init(&_lock, attr); }
	~MutexLock() { pthread_mutex_destroy(&_lock); }
	inline int lock() { return pthread_mutex_lock(&_lock); }
	inline int unlock() { return pthread_mutex_unlock(&_lock); }
	inline int trylock() { return pthread_mutex_trylock(&_lock); }
private:
	pthread_mutex_t _lock;

private:
	MutexLock(const MutexLock &) { }
	MutexLock & operator = (const MutexLock &) {return *this;}

	friend class CondLock;
};

class AutoMutexLock
{
public:
	AutoMutexLock (MutexLock &l) : _lock(&l) { _lock->lock(); }
	~AutoMutexLock() { _lock->unlock(); }
private:
	MutexLock *_lock;
};

class CondLock
{
	//     pthread_cond_broadcast(3), pthread_cond_destroy(3), pthread_cond_init(3), pthread_cond_timedwait(3), pthread_cond_wait(3), pthread_cond_signal(3)
public:
	CondLock(const pthread_condattr_t *attr=NULL) {
		pthread_cond_init(&_cond, attr);
	}
	~CondLock() {
		pthread_cond_destroy(&_cond);
	}

	int broadcast() {
		return pthread_cond_broadcast(&_cond);
	}
	int timedwait(MutexLock &l, const struct timespec *abs) {
		return pthread_cond_timedwait(&_cond, &l._lock, abs);
	}
	int wait(MutexLock &l) {
		return pthread_cond_wait(&_cond, &l._lock);
	}
	int signal() {
		return pthread_cond_signal(&_cond);
	}
private:
	pthread_cond_t _cond;
};


template <typename T>
class MsgQ
{
private:
	typename std::deque<T> _deque;
	int _size;
	CondLock _cond;
	MutexLock _lock;
public:
	MsgQ() : _size(1<<29) {}
	inline void set_max_size(int size) { _size = size; }
	inline bool full() { _deque.size() >= _size; }

	int push(const T & val, int ms = -1) {
		AutoMutexLock __auto(_lock);
		if (full()) {
			if (ms < 0) {
				while (full()) {
					_cond.wait(_lock);
				}
			} else if (ms == 0) {
				return -1;
			} else {
				struct timespec abs;
				abs.tv_sec = ms / 1000;
				abs.tv_nsec = (ms % 1000) * 1000000;
				_cond.timedwait(_lock, &abs);

			}
			if (full()) { return -1; }
		}

		_deque.push_back(val);
		
		return 0;
	}
	int pop(T *val, int ms = -1) {
		AutoMutexLock __auto(_lock);
		if (_deque.size() == 0) {
			return -1;
		} else {
			*val = _deque.front();
			_deque.pop_front();
		}
		return 0;
	}
};

class ThreadPool
{
public:
	class IEvent 
	{
	public:
		enum {
			INIT = 0,
			RUN = 100000,
			DONE = 100001
		};
		virtual ~IEvent() {}
		virtual void cb() = 0;
		virtual void setStatus(int) = 0;
		virtual int status() const = 0;
	};
	class Event : public IEvent
	{
	public:
		void setStatus(int s) { _status = s; }
		int status() const { return _status; }

		Event() : _status(INIT) {}
	private:
		int _status;
	};

	int createEvent(IEvent *ev);

	int run(int num);
	int join();

public:
	ThreadPool();
	~ThreadPool();

	void dispatch();
private:
	MsgQ<IEvent *> _msgq;
	std::vector<pthread_t> _vec;
};

};
#endif
